#ifndef __MY_SQL_CON_POOL_H__
#define __MY_SQL_CON_POOL_H__

#include <string>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <iostream>

#include <mysql/mysql.h>

class MySqlPool 
{
public:
    // --- RAII代理类 ---
    class ConnectionGuard 
    {
    public:
        ConnectionGuard(MySqlPool& pool, MYSQL* conn)
            : _pool(pool), conn_(conn) {}
        ~ConnectionGuard() 
        {
            if (conn_) {
                _pool.returnConnection(conn_);
            }
        }
        ConnectionGuard(const ConnectionGuard&) = delete;
        ConnectionGuard& operator=(const ConnectionGuard&) = delete;

        ConnectionGuard(ConnectionGuard&& other) noexcept
            : _pool(other._pool), conn_(other.conn_) {
            other.conn_ = nullptr;
        }

        ConnectionGuard& operator=(ConnectionGuard&& other) noexcept 
        {
            if (this != &other) 
            {
                if (conn_) _pool.returnConnection(conn_);
                conn_ = other.conn_;
                other.conn_ = nullptr;
            }
            return *this;
        }

        MYSQL* get() const { return conn_; }
        MYSQL* operator->() const { return conn_; }
        MYSQL& operator*() const { return *conn_; }

    private:
        MySqlPool& _pool;
        MYSQL* conn_;
    };

public:
    // MySqlPool(const std::string& host, unsigned int port,
    //           const std::string& user, const std::string& pass,
    //           const std::string& db, int poolSize);
    MySqlPool();

    ~MySqlPool() { close(); }

    // 获取一个RAII封装的连接
    ConnectionGuard acquire();

    void close();
    void show();

private:
    // 创建一个新的连接
    MYSQL* createConnection();
    // 从连接池中获取一个连接
    MYSQL* getConnection();
    // 返回一个连接回池中
    void returnConnection(MYSQL* conn);
private:
    std::string _host;
    unsigned int _port;
    std::string _user;
    std::string _pass;
    std::string _db;
    int _poolSize;

    std::queue<MYSQL*> _pool;
    std::mutex _mutex;
    std::condition_variable _cond;
    std::atomic<bool> _stop;
};


#endif // !__MY_SQL_CON_POOL_H__